/*
 * Main.java
 *
 * Created on July 30, 2007, 4:48 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.atomojo.auth.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.DateFormat;
import java.util.Date;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import org.atomojo.auth.service.Configuration.Host;
import org.atomojo.auth.service.db.AuthDB;
import org.infoset.xml.util.WriterItemDestination;

/**
 *
 * @author alex
 */
public class Main
{
   
   class DebugHandler extends Handler {
      public void publish(LogRecord record) {
         if (record.getLevel().intValue()<=logLevel.intValue()) {
            DateFormat format = DateFormat.getDateTimeInstance();
            String dateTime = format.format(new Date(record.getMillis()));
            System.err.println(dateTime+" "+record.getSourceClassName()+" "+record.getSourceMethodName());
            System.err.println(record.getLevel()+": "+record.getMessage());
         }
      }
      
      public void flush() {
         
      }
      
      public void close() {
         
      }
   }
   
   File confFile;
   File dbDir;
   File keystoreFile;
   AuthDB db;
   Configuration conf;
   WebComponent www;
   Level logLevel = Level.INFO;
   boolean create;
   
   /** Creates a new instance of Main */
   public Main(File parent)
   {
      confFile = new File(parent,"conf.xml");
      keystoreFile = new File(parent,"keystore");
      dbDir = new File(parent,"db");
   }
   
   public void setLogLevel(Level level)
   {
      logLevel = level;
   }
   
   public void init() {
      try {
         System.out.println("Setting log level to "+logLevel);
         Logger log = Logger.getLogger(WebComponent.LOG_NAME);
         log.setLevel(logLevel);
         log = Logger.getLogger("org.atomojo");
         log.setLevel(logLevel);
         if (logLevel!=Level.INFO) {
            log.addHandler(new DebugHandler());
         }
         
         db = new AuthDB("auth","jdbc:derby:"+dbDir.getAbsolutePath()+";create=true");
         
         conf = new Configuration();
         if (!confFile.exists()) {
            create = true;
         } else {
            conf.load(confFile.toURI());
            create = false;
            www = new WebComponent(conf,db);
         }
      } catch (Exception ex) {
         ex.printStackTrace();
      }
   }
   
   public void run() {
      try {
         
         if (create) {
            Configuration.Interface iface = new Configuration.Interface("*",8080,false);
            iface.getHosts().put("*",new Host("*",null));
            conf.getInterfaces().add(iface);
            conf.setKeyStorePath(keystoreFile);
            conf.setKeyStorePassword("atomojo");
            conf.setKeyPassword("atomojo");
            Writer w = new OutputStreamWriter(new FileOutputStream(confFile),"UTF-8");
            conf.store(confFile.toURI(),new WriterItemDestination(w,"UTF-8"));
            w.flush();
            w.close();
            if (!keystoreFile.exists()) {
               copyResource("/org/atomojo/auth/service/keystore",keystoreFile);
            }
            www = new WebComponent(conf,db);
            
         }
         
         db.connect();
         
         www.start();
         www.getLogger().info("Started.");
      } catch (Exception ex) {
         ex.printStackTrace();
      }
   }
   
   public void stop() {
      try {
         www.stop();
      } catch (Exception ex) {
         ex.printStackTrace();
      }
   }
   
   static void copyResource(String resourcePath,File outFile)
      throws IOException
   {
      InputStream in = Main.class.getResourceAsStream(resourcePath);
      if (in==null) {
         throw new IOException("Cannot open resource "+resourcePath);
      }
      FileOutputStream out = new FileOutputStream(outFile);
      byte [] buffer = new byte[8192];
      int len;
      while ((len=in.read(buffer))>0) {
         out.write(buffer,0,len);
      }
      out.close();
      in.close();
   }
   
   /**
    * @param args the command line arguments
    */
   public static void main(String[] args)
   {
      int argIndex = 0;
      Level logLevel = Level.INFO;
      while (argIndex<args.length && args[argIndex].charAt(0)=='-') {
         String name = args[argIndex].substring(1);
         argIndex++;
         if (argIndex==args.length) {
            throw new RuntimeException("The argument "+args[argIndex]+" requires an argument.");
         }
         if (name.equals("l") || name.equals("-level")) {
            if (args[argIndex].equals("info")) {
               logLevel = Level.INFO;
            } else if (args[argIndex].equals("fine")) {
               logLevel = Level.FINE;
            } else if (args[argIndex].equals("finer")) {
               logLevel = Level.FINER;
            } else if (args[argIndex].equals("finest")) {
               logLevel = Level.FINEST;
            } else if (args[argIndex].equals("config")) {
               logLevel = Level.CONFIG;
            }
         }
         argIndex++;
      }
      int argCount = args.length-argIndex;
      
      if (argCount!=1) {
         System.err.println("Usage: org.atomojo.auth.service.Main {options} dir");
         System.exit(1);
      }
      File dir = new File(args[argIndex]);
      if (!dir.exists()) {
         System.err.println("The directory "+args[argIndex]+" does not exist.");
         System.exit(1);
      }
      if (!dir.isDirectory()) {
         System.err.println("The path "+args[argIndex]+" is not a directory.");
         System.exit(1);
      }
      if (!dir.canRead() || !dir.canWrite()) {
         System.err.println("The directory "+args[argIndex]+" is not both readable and writeable.");
         System.exit(1);
      }
      Main main = new Main(dir);
      main.setLogLevel(logLevel);
      main.init();
      main.run();
   }   
}
